<script setup lang="ts">
import type TreeSelectProp from "./type/TreeSelectProp.ts";
import type SelectEmit from "@/components/select/type/SelectEmit.ts";
import {computed, ref, watch} from "vue";
import {mixHexWithWhite} from "@/components/utils.ts";
import type SelectItem from "@/components/select/type/SelectItem.ts";
import type TreeNodeProp from "@/components/tree/TreeNodeProp.ts";

const $emit = defineEmits<SelectEmit>()

const $prop = withDefaults(defineProps<TreeSelectProp>(), {
  placeholder: '请选择...',
  labelWidth: 80,
  required: false,
  borderColor: "#1c7bfb",
  searchable: false,
  multiple: true,
  options: () => []
})

//选择框是否获得焦点
const focused = ref(false)
// 下拉框是否显示
const isShow = ref(false)
// 已选择的item
const selectedItems = ref<SelectItem[]>([])
// 计算已选择的数量
const selectedCount = computed(() => selectedItems.value.length)
// 搜索内容
const searchText = ref<string>()
// 边框颜色处理
const lightBorderColor = computed(() => mixHexWithWhite($prop.borderColor!, 0.85))


const nodeChecked = (id: string, checked: boolean) => {
  console.log(id, checked, map)
  if (checked) {
    itemChange({value: id, label: map.get(id)!})
  } else {
    itemClose(id)
  }
}

const itemChange = (item: SelectItem) => {
  // 单选
  if (!$prop.multiple) {
    selectedItems.value.length = 0
    selectedItems.value.push(item)
    isShow.value = false
  }
  // 多选
  else {
    const index = selectedItems.value.findIndex(i => i.value === item.value)
    // 如果该元素存在，则移除
    if (index > -1) {
      selectedItems.value.splice(index, 1);
    }
    // 否则添加
    else {
      selectedItems.value.push(item)
    }
  }

  updateModelValue(item.value)
}

const itemClose = (code: string | number) => {
  const index = selectedItems.value.findIndex(i => i.value === code)
  if (index > -1) {
    selectedItems.value.splice(index, 1);
  }

  updateModelValue(code)
}

const updateModelValue = (key: string | number | boolean) => {
  let newVal = [...selectedItems.value.map(i => i.value)]
  // 修改modelValue双向数据
  $emit('update:modelValue', newVal)
}

const checkedKeys = computed(() => {
  return $prop.modelValue.map(item => String(item))
})

const clear = () => {
  selectedItems.value.length = 0
}

const map = new Map<string, string>()

const dfs = (trees: TreeNodeProp[] | undefined) => {
  if (trees) {
    trees.forEach(item => {
      map.set(item.id, item.key)
      if (item.children) {
        dfs(item.children)
      }
    })
  }
}

watch(
    () => $prop.data,
    (newVal) => {
      if (!newVal || newVal.length === 0) return;

      // 清空 map 和 selectedItems，避免重复 push
      map.clear();
      selectedItems.value = [];

      dfs(newVal)

      const modelValues = $prop.modelValue.map(item => String(item))
      modelValues.forEach(item => {
        const label = map.get(item)
        if (label !== undefined) {
          selectedItems.value.push({value: item, label})
        }
      })
    },
    {immediate: true} // 一开始就触发一次
)

</script>

<template>
  <div class="select-container" ref="selectContainer">

    <!-- 标题 -->
    <template v-if="label">
      <div class="select-label">
        <span>{{ label }}</span>
        <span v-if="required" style="color: #d03050">&nbsp;*</span>
        <span v-else style="visibility: hidden">&nbsp;*</span>
      </div>

    </template>

    <!-- 下拉框 -->
    <div class="select-content">
      <t-floating v-model="isShow" :offset="1" trigger="click">

        <!-- 下拉框触发器 -->
        <div tabindex="-1" ref="selectBodyRef" class="select-body" :class="{focused}" @focus="focused = true" @blur="focused = false">

          <span v-if="!selectedItems || selectedItems.length === 0"
                style="color: #757575; font-size: 14px">{{ placeholder }}</span>

          <t-tag v-for="(item, index) in selectedItems"
                 ref="tagRefs"
                 v-show="selectedCount <= 2 || index < 2"
                 :type="item.type ?? 'primary'"
                 :code="item.value" :key="item.value" :label="item.label"
                 @close="(code: string | number) => itemClose(code)" closeable @click.stop/>

          <span class="more-text" v-if=" selectedCount > 2">
              ...等{{ selectedCount }}项
          </span>

          <component class="arrow-down" is="arrow-down" style="color: #c2c2c2"/>
        </div>

        <template #floating>
          <t-tree :data="data" :checked-keys="checkedKeys" @checked="nodeChecked" check default-expanded/>
        </template>
      </t-floating>
    </div>

  </div>
</template>

<style scoped>
.select-container {
  display: flex;
  align-items: center;
  width: 100%;
  line-height: 1;
  font-size: 14px;
  margin: 4px;
  gap: 3px;
}

.select-label {
  width: v-bind(labelWidth+ 'px');
  text-align: right;
}

.select-content {
  height: 30px;
  width: calc(100% - v-bind(labelWidth+ "px") - 8px);
}

.select-body {
  height: 30px;
  border: 1px solid #e0e0e6;
  border-radius: 2px;
  cursor: pointer;
  display: flex;
  align-items: center;
  padding: 0 4px;
  gap: 2px;
  overflow: hidden;
  position: relative;

  background-color: white;
  box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.08), inset -1px -1px 1px rgba(255, 255, 255, 0.6);
}

.more-text {
  color: #666;
  font-size: 12px;
  white-space: nowrap;
  margin-left: 4px;
}

.select-body:hover {
  border-color: v-bind(borderColor);
}

.select-body.focused {
  border-color: v-bind(borderColor);
  box-shadow: 0 0 0 2px v-bind(lightBorderColor);
}

.arrow-down {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
}


</style>